package org.nbict.iot.protocol.type;

import org.nbict.iot.protocol.Convertor;
import org.nbict.iot.protocol.util.BytesOperator;
import org.nbict.iot.protocol.util.ScalingUnit;

import java.math.BigInteger;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;

/**
 * 数值单位转换
 * Created by songseven on 18/6/13.
 */
public enum FieldValueCast implements Convertor {

    /**
     * byte[]转时间戳
     */
    TIMESTAMP {
        @Override
        public Long convert(byte[] value, ProtocolField field) {
            LocalDateTime date = LocalDateTime.of(
                    2000 + value[0], value[1], value[2], value[3], value[4],
                    value[5]);
            return date.toEpochSecond(ZoneOffset.of("+8"));
        }
    },

    /**
     * byte[]整型
     */
    INT {
        @Override
        public Integer convert(byte[] value, ProtocolField field) {
            byte[] unsignedValue = BytesOperator.byteMerger(new byte[]{0x00},
                    value);
            BigInteger bi = new BigInteger(unsignedValue);
            if (field.getUnit() != null && !field.getUnit().isEmpty()) {
                bi = ScalingUnit.scale(field, bi).toBigInteger();
            }
            return bi.intValue();
        }
    },

    /**
     * byte[]字符串
     */
    STRING {
        @Override
        public String convert(byte[] value, ProtocolField field) {
            return BytesOperator.bytesToString(value);
        }
    },

    /**
     * byte[]16进制字符串
     */
    HEXSTRING {
        @Override
        public String convert(byte[] value, ProtocolField field) {
            return BytesOperator.bytesToHexString(value);
        }
    },

    /**
     * byte[]双字数字数组
     */
    WORDN {
        @Override
        public List convert(byte[] value, ProtocolField field) {
            //2 byte
            List<Integer> res = new ArrayList<>();
            for (int i = 0; i < value.length; i += 2) {
                byte[] a = BytesOperator.splitBytes(value, i, 2);
                res.add((Integer) INT.convert(a, field));
            }
            return res;
        }
    },

    /**
     * byte[]四字数字数组
     */
    DWORDN {
        @Override
        public List convert(byte[] value, ProtocolField field) {
            //4 byte
            List<Integer> res = new ArrayList<>();
            for (int i = 0; i < value.length; i += 4) {
                byte[] a = BytesOperator.splitBytes(value, i, 4);
                res.add((Integer) INT.convert(a, field));
            }
            return res;
        }
    },

    /**
     * byte[]单字数字数组
     */
    BYTEN {
        @Override
        public List convert(byte[] value, ProtocolField field) {
            //1 byte
            List<Integer> res = new ArrayList<>();
            for (int i = 0; i < value.length; i++) {
                byte[] a = BytesOperator.splitBytes(value, i, 1);
                res.add((Integer) INT.convert(a, field));
            }
            return res;
        }
    },

    /**
     * byte[]单精度数字
     */
    FLOAT {
        @Override
        public Float convert(byte[] value, ProtocolField field) {
            byte[] unsignedValue = BytesOperator.byteMerger(new byte[]{0x00},
                    value);
            BigInteger bi = new BigInteger(unsignedValue);

            Float out = 0.0f;
            if ( field.getUnit() != null && !field.getUnit().isEmpty()) {
                out = ScalingUnit.scale(field, bi).floatValue();
            } else {
                out = bi.floatValue();
            }
            return out;
        }
    },

    /**
     * byte[]双精度数字
     */
    DOUBLE {
        @Override
        public Double convert(byte[] value, ProtocolField field) {
            byte[] unsignedValue = BytesOperator.byteMerger(new byte[]{0x00},
                    value);
            BigInteger bi = new BigInteger(unsignedValue);

            Double out = 0.00d;
            if (field.getUnit() != null && !field.getUnit().isEmpty()) {
                out = ScalingUnit.scale(field, bi).doubleValue();
            } else {
                out = bi.doubleValue();
            }
            return out;
        }
    },

    /**
     * byte[]三精度数字
     */
    TRIPLE {
        @Override
        public Double convert(byte[] value, ProtocolField field) {

            byte[] unsignedValue = BytesOperator.byteMerger(new byte[]{0x00},
                    value);
            BigInteger bi = new BigInteger(unsignedValue);

            Double out = null;
            if (field.getUnit() != null && !field.getUnit().isEmpty()) {
                out = ScalingUnit.scale(field, bi).setScale(3,  RoundingMode.HALF_UP).doubleValue();
            } else {
                out = bi.doubleValue();
            }
            return out;
        }
    },
    /**
     * byte[]双字三精度数字数组
     */
    TRIPLEN {
        @Override
        public List convert(byte[] value, ProtocolField field) {
            //2 byte
            List res = new ArrayList<>();
            for (int i = 0; i < value.length; i += 2) {
                byte[] a = BytesOperator.splitBytes(value, i, 2);
                res.add(TRIPLE.convert(a, field));
            }
            return res;
        }
    };

//    public static void main(String[] args) {
//        //byte[] value = {0x12,0x07,0x02,0x05,0x22,0x0d};
//        byte[] value = {0x12,0x07,0x02,0x05,0x28,0x2b};
//        LocalDateTime date = LocalDateTime.of(
//                2000 + value[0], value[1], value[2], value[3], value[4],
//                value[5]);
//        System.out.println(date.toEpochSecond(ZoneOffset.of("+8")));
//    }
}
